//
// Created by benxb on 2021/12/8.
//

#include <gtest/gtest.h>
#include <mem/data_table_manager.h>
#include <catelog/table.h>
#include <vector>
#include <catelog/column.h>
#include <cstdio>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <ctime>

TEST(TableManagerTest, AppendRecord) {
    std::vector<benxdb::Column> columns;
    columns.emplace_back("x", benxdb::FLOAT);
    columns.emplace_back("y", benxdb::FLOAT);
    columns.emplace_back("z", benxdb::FLOAT);
//    columns.emplace_back("intensity", benxdb::FLOAT);
    benxdb::DataTableManager manager(std::make_shared<benxdb::Table>("test", columns));

//    srand((unsigned)time(NULL));
    for (int i = 0; i < 1289; i++) {
        std::vector<benxdb::Value> vals;
        vals.emplace_back(benxdb::FLOAT, (float)(rand()%400000));
        vals.emplace_back(benxdb::FLOAT, (float)(rand()%400000));
        vals.emplace_back(benxdb::FLOAT, (float)(rand()%400000));
//    vals.emplace_back(benxdb::FLOAT, (float)rand());
        auto tuple = benxdb::Tuple(vals);
        manager.AppendTuple(tuple);
    }
}

TEST(TableManagerTest, SimpleQuery) {
    benxdb::DataTableManager manager(std::make_shared<benxdb::Table>("test"));
    auto start = std::chrono::steady_clock::now();
    std::vector<benxdb::Tuple> res;
    benxdb::QueryPhrase query("test");
    query.Select({"x", "y", "z"});
    query.Where("x", benxdb::LESS_THAN, benxdb::Value(benxdb::FLOAT, 10.f));
    query.Where("x", benxdb::GREATER_THAN, benxdb::Value(benxdb::FLOAT, -10.f));
    query.Where("y", benxdb::LESS_THAN, benxdb::Value(benxdb::FLOAT, 10.f));
    query.Where("y", benxdb::GREATER_THAN, benxdb::Value(benxdb::FLOAT, -10.f));
    manager.Query(query, res);
//    for (benxdb::Tuple& t : res) {
//        benxdb::Value vl;
//        t.GetValue(0, vl);
//        float ft = vl.GetAs<float>();
//        if (ft >= 20 || ft <= -20) {
//            std::cout << ft << " ";
//        }
//        t.GetValue(1, vl);
//        ft = vl.GetAs<float>();
//        if (ft >= 20 || ft <= -20) {
//            std::cout << ft << " ";
//        }
//    }
    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
    std::cout << "SimpleQuery End, spend " << time_span.count() << std::endl;
    std::cout << res.size() << std::endl;
}


TEST(TableManagerTest, SimpleQueryPointCloud) {
    benxdb::DataTableManager manager(std::make_shared<benxdb::Table>("test"));
    auto start = std::chrono::steady_clock::now();
    benxdb::PointCloud<benxdb::PointXYZ> res;
    benxdb::RectangleQuery query("test");
    query.SetRectangle(-10, 10, -10, 10);
    manager.QueryPointCloud(query, res);
    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
    std::cout << "SimpleQueryPointCloud End, spend " << time_span.count() << std::endl;
    std::cout << res.Size() << std::endl;
}

std::string data_file = "/home/ubuntu/benxdb/data/test.data";

TEST(TableManagerTest, OirginQuery) {
    std::fstream io(data_file, std::ios::binary | std::ios::in | std::ios::out);
    std::vector<float> x_arr;
    std::vector<float> y_arr;
    std::vector<float> z_arr;

    int total_count = 0;
    while (!io.eof()) {
        total_count++;
        std::vector<float> x_c, y_c, z_c;
        float x, y, z;
        for (int i = 0; i < benxdb::RECORD_COUNT_PER_CHUNK; i++) {
            io.read(reinterpret_cast<char *>(&x), sizeof(x));
            x_c.push_back(x);
        }
        for (int i = 0; i < benxdb::RECORD_COUNT_PER_CHUNK; i++) {
            io.read(reinterpret_cast<char *>(&y), sizeof(y));
            y_c.push_back(y);
        }
        for (int i = 0; i < benxdb::RECORD_COUNT_PER_CHUNK; i++) {
            io.read(reinterpret_cast<char *>(&z), sizeof(z));
            z_c.push_back(z);
        }
        for (int i = 0; i < benxdb::RECORD_COUNT_PER_CHUNK; i++) {
            x = x_c[i];
            y = y_c[i];
            z = z_c[i];
            if (x > 0 && x < 40 && y < 40 && y > 0) {
                x_arr.push_back(x);
                y_arr.push_back(y);
                z_arr.push_back(z);
            }
        }
    }
    std::cout << total_count*benxdb::RECORD_COUNT_PER_CHUNK << " " << x_arr.size() << std::endl;
    io.close();
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc,argv);
    return RUN_ALL_TESTS();
}